@planu/cli 0.28.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/model-routing-rules.json +98 -0
- package/dist/engine/ai-cost-estimator/core.d.ts.map +1 -1
- package/dist/engine/ai-cost-estimator/core.js +2 -202
- package/dist/engine/ai-cost-estimator/core.js.map +1 -1
- package/dist/engine/ai-cost-estimator/recommender.d.ts +8 -0
- package/dist/engine/ai-cost-estimator/recommender.d.ts.map +1 -0
- package/dist/engine/ai-cost-estimator/recommender.js +94 -0
- package/dist/engine/ai-cost-estimator/recommender.js.map +1 -0
- package/dist/engine/ai-cost-estimator/spec-loader.d.ts +13 -0
- package/dist/engine/ai-cost-estimator/spec-loader.d.ts.map +1 -0
- package/dist/engine/ai-cost-estimator/spec-loader.js +102 -0
- package/dist/engine/ai-cost-estimator/spec-loader.js.map +1 -0
- package/dist/engine/ci-generator/planu-config.d.ts +7 -0
- package/dist/engine/ci-generator/planu-config.d.ts.map +1 -0
- package/dist/engine/ci-generator/planu-config.js +40 -0
- package/dist/engine/ci-generator/planu-config.js.map +1 -0
- package/dist/engine/ci-generator/planu-steps.d.ts +11 -0
- package/dist/engine/ci-generator/planu-steps.d.ts.map +1 -0
- package/dist/engine/ci-generator/planu-steps.js +292 -0
- package/dist/engine/ci-generator/planu-steps.js.map +1 -0
- package/dist/engine/code-transforms/transform-engine.d.ts +7 -0
- package/dist/engine/code-transforms/transform-engine.d.ts.map +1 -0
- package/dist/engine/code-transforms/transform-engine.js +67 -0
- package/dist/engine/code-transforms/transform-engine.js.map +1 -0
- package/dist/engine/code-transforms/typescript/add-error-handling.d.ts +6 -0
- package/dist/engine/code-transforms/typescript/add-error-handling.d.ts.map +1 -0
- package/dist/engine/code-transforms/typescript/add-error-handling.js +92 -0
- package/dist/engine/code-transforms/typescript/add-error-handling.js.map +1 -0
- package/dist/engine/code-transforms/typescript/add-jsdoc.d.ts +6 -0
- package/dist/engine/code-transforms/typescript/add-jsdoc.d.ts.map +1 -0
- package/dist/engine/code-transforms/typescript/add-jsdoc.js +83 -0
- package/dist/engine/code-transforms/typescript/add-jsdoc.js.map +1 -0
- package/dist/engine/code-transforms/typescript/add-types.d.ts +3 -0
- package/dist/engine/code-transforms/typescript/add-types.d.ts.map +1 -0
- package/dist/engine/code-transforms/typescript/add-types.js +182 -0
- package/dist/engine/code-transforms/typescript/add-types.js.map +1 -0
- package/dist/engine/code-transforms/typescript/ast-utils.d.ts +38 -0
- package/dist/engine/code-transforms/typescript/ast-utils.d.ts.map +1 -0
- package/dist/engine/code-transforms/typescript/ast-utils.js +90 -0
- package/dist/engine/code-transforms/typescript/ast-utils.js.map +1 -0
- package/dist/engine/code-transforms/typescript/extract-interface.d.ts +6 -0
- package/dist/engine/code-transforms/typescript/extract-interface.d.ts.map +1 -0
- package/dist/engine/code-transforms/typescript/extract-interface.js +103 -0
- package/dist/engine/code-transforms/typescript/extract-interface.js.map +1 -0
- package/dist/engine/code-transforms/typescript/modernize-syntax.d.ts +3 -0
- package/dist/engine/code-transforms/typescript/modernize-syntax.d.ts.map +1 -0
- package/dist/engine/code-transforms/typescript/modernize-syntax.js +213 -0
- package/dist/engine/code-transforms/typescript/modernize-syntax.js.map +1 -0
- package/dist/engine/code-transforms/typescript/rename-symbol.d.ts +8 -0
- package/dist/engine/code-transforms/typescript/rename-symbol.d.ts.map +1 -0
- package/dist/engine/code-transforms/typescript/rename-symbol.js +40 -0
- package/dist/engine/code-transforms/typescript/rename-symbol.js.map +1 -0
- package/dist/engine/mermaid/core.d.ts +18 -0
- package/dist/engine/mermaid/core.d.ts.map +1 -0
- package/dist/engine/mermaid/core.js +88 -0
- package/dist/engine/mermaid/core.js.map +1 -0
- package/dist/engine/mermaid/diagram-generators.d.ts +22 -0
- package/dist/engine/mermaid/diagram-generators.d.ts.map +1 -0
- package/dist/engine/mermaid/diagram-generators.js +139 -0
- package/dist/engine/mermaid/diagram-generators.js.map +1 -0
- package/dist/engine/mermaid/helpers.d.ts +8 -0
- package/dist/engine/mermaid/helpers.d.ts.map +1 -0
- package/dist/engine/mermaid/helpers.js +61 -0
- package/dist/engine/mermaid/helpers.js.map +1 -0
- package/dist/engine/mermaid-generator.d.ts +2 -37
- package/dist/engine/mermaid-generator.d.ts.map +1 -1
- package/dist/engine/mermaid-generator.js +4 -276
- package/dist/engine/mermaid-generator.js.map +1 -1
- package/dist/engine/model-router/complexity-analyzer.d.ts +26 -0
- package/dist/engine/model-router/complexity-analyzer.d.ts.map +1 -0
- package/dist/engine/model-router/complexity-analyzer.js +182 -0
- package/dist/engine/model-router/complexity-analyzer.js.map +1 -0
- package/dist/engine/model-router/cost-estimator.d.ts +6 -0
- package/dist/engine/model-router/cost-estimator.d.ts.map +1 -0
- package/dist/engine/model-router/cost-estimator.js +60 -0
- package/dist/engine/model-router/cost-estimator.js.map +1 -0
- package/dist/engine/model-router/historical-learner.d.ts +26 -0
- package/dist/engine/model-router/historical-learner.d.ts.map +1 -0
- package/dist/engine/model-router/historical-learner.js +91 -0
- package/dist/engine/model-router/historical-learner.js.map +1 -0
- package/dist/engine/model-router/rules-engine.d.ts +13 -0
- package/dist/engine/model-router/rules-engine.d.ts.map +1 -0
- package/dist/engine/model-router/rules-engine.js +142 -0
- package/dist/engine/model-router/rules-engine.js.map +1 -0
- package/dist/engine/spec-coverage/criteria-mapper.d.ts +1 -2
- package/dist/engine/spec-coverage/criteria-mapper.d.ts.map +1 -1
- package/dist/engine/spec-coverage/criteria-mapper.js +4 -203
- package/dist/engine/spec-coverage/criteria-mapper.js.map +1 -1
- package/dist/engine/spec-coverage/keyword-extractor.d.ts +10 -0
- package/dist/engine/spec-coverage/keyword-extractor.d.ts.map +1 -0
- package/dist/engine/spec-coverage/keyword-extractor.js +147 -0
- package/dist/engine/spec-coverage/keyword-extractor.js.map +1 -0
- package/dist/engine/spec-coverage/test-matchers.d.ts +9 -0
- package/dist/engine/spec-coverage/test-matchers.d.ts.map +1 -0
- package/dist/engine/spec-coverage/test-matchers.js +59 -0
- package/dist/engine/spec-coverage/test-matchers.js.map +1 -0
- package/dist/engine/spec-templates/catalog-extra.d.ts +1 -1
- package/dist/engine/spec-templates/catalog-extra.d.ts.map +1 -1
- package/dist/engine/spec-templates/catalog-extra.js +8 -363
- package/dist/engine/spec-templates/catalog-extra.js.map +1 -1
- package/dist/engine/spec-templates/catalog-industry.d.ts +4 -0
- package/dist/engine/spec-templates/catalog-industry.d.ts.map +1 -0
- package/dist/engine/spec-templates/catalog-industry.js +19 -0
- package/dist/engine/spec-templates/catalog-industry.js.map +1 -0
- package/dist/engine/spec-templates/catalog.d.ts +1 -1
- package/dist/engine/spec-templates/catalog.d.ts.map +1 -1
- package/dist/engine/spec-templates/catalog.js +12 -381
- package/dist/engine/spec-templates/catalog.js.map +1 -1
- package/dist/engine/spec-templates/custom-loader.d.ts +12 -0
- package/dist/engine/spec-templates/custom-loader.d.ts.map +1 -0
- package/dist/engine/spec-templates/custom-loader.js +99 -0
- package/dist/engine/spec-templates/custom-loader.js.map +1 -0
- package/dist/engine/spec-templates/index.d.ts +4 -2
- package/dist/engine/spec-templates/index.d.ts.map +1 -1
- package/dist/engine/spec-templates/index.js +4 -2
- package/dist/engine/spec-templates/index.js.map +1 -1
- package/dist/engine/spec-templates/query.d.ts +12 -4
- package/dist/engine/spec-templates/query.d.ts.map +1 -1
- package/dist/engine/spec-templates/query.js +29 -7
- package/dist/engine/spec-templates/query.js.map +1 -1
- package/dist/engine/spec-templates/renderer.d.ts +27 -2
- package/dist/engine/spec-templates/renderer.d.ts.map +1 -1
- package/dist/engine/spec-templates/renderer.js +119 -4
- package/dist/engine/spec-templates/renderer.js.map +1 -1
- package/dist/engine/spec-templates/templates-api-ui.d.ts +6 -0
- package/dist/engine/spec-templates/templates-api-ui.d.ts.map +1 -0
- package/dist/engine/spec-templates/templates-api-ui.js +215 -0
- package/dist/engine/spec-templates/templates-api-ui.js.map +1 -0
- package/dist/engine/spec-templates/templates-auth-crud.d.ts +6 -0
- package/dist/engine/spec-templates/templates-auth-crud.d.ts.map +1 -0
- package/dist/engine/spec-templates/templates-auth-crud.js +225 -0
- package/dist/engine/spec-templates/templates-auth-crud.js.map +1 -0
- package/dist/engine/spec-templates/templates-data-security.d.ts +6 -0
- package/dist/engine/spec-templates/templates-data-security.d.ts.map +1 -0
- package/dist/engine/spec-templates/templates-data-security.js +198 -0
- package/dist/engine/spec-templates/templates-data-security.js.map +1 -0
- package/dist/engine/spec-templates/templates-industry-ecom.d.ts +6 -0
- package/dist/engine/spec-templates/templates-industry-ecom.d.ts.map +1 -0
- package/dist/engine/spec-templates/templates-industry-ecom.js +209 -0
- package/dist/engine/spec-templates/templates-industry-ecom.js.map +1 -0
- package/dist/engine/spec-templates/templates-industry-fintech.d.ts +8 -0
- package/dist/engine/spec-templates/templates-industry-fintech.d.ts.map +1 -0
- package/dist/engine/spec-templates/templates-industry-fintech.js +350 -0
- package/dist/engine/spec-templates/templates-industry-fintech.js.map +1 -0
- package/dist/engine/spec-templates/templates-industry-health-ecom.d.ts +3 -0
- package/dist/engine/spec-templates/templates-industry-health-ecom.d.ts.map +1 -0
- package/dist/engine/spec-templates/templates-industry-health-ecom.js +5 -0
- package/dist/engine/spec-templates/templates-industry-health-ecom.js.map +1 -0
- package/dist/engine/spec-templates/templates-industry-health.d.ts +6 -0
- package/dist/engine/spec-templates/templates-industry-health.d.ts.map +1 -0
- package/dist/engine/spec-templates/templates-industry-health.js +208 -0
- package/dist/engine/spec-templates/templates-industry-health.js.map +1 -0
- package/dist/engine/spec-templates/templates-industry-saas.d.ts +8 -0
- package/dist/engine/spec-templates/templates-industry-saas.d.ts.map +1 -0
- package/dist/engine/spec-templates/templates-industry-saas.js +323 -0
- package/dist/engine/spec-templates/templates-industry-saas.js.map +1 -0
- package/dist/engine/spec-templates/templates-perf-integration.d.ts +6 -0
- package/dist/engine/spec-templates/templates-perf-integration.d.ts.map +1 -0
- package/dist/engine/spec-templates/templates-perf-integration.js +226 -0
- package/dist/engine/spec-templates/templates-perf-integration.js.map +1 -0
- package/dist/engine/vector-store/hnsw.d.ts +37 -0
- package/dist/engine/vector-store/hnsw.d.ts.map +1 -0
- package/dist/engine/vector-store/hnsw.js +294 -0
- package/dist/engine/vector-store/hnsw.js.map +1 -0
- package/dist/engine/vector-store/similarity.d.ts +21 -0
- package/dist/engine/vector-store/similarity.d.ts.map +1 -0
- package/dist/engine/vector-store/similarity.js +86 -0
- package/dist/engine/vector-store/similarity.js.map +1 -0
- package/dist/engine/vector-store/tfidf.d.ts +35 -0
- package/dist/engine/vector-store/tfidf.d.ts.map +1 -0
- package/dist/engine/vector-store/tfidf.js +255 -0
- package/dist/engine/vector-store/tfidf.js.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/storage/vector-store/backend-factory.d.ts +9 -0
- package/dist/storage/vector-store/backend-factory.d.ts.map +1 -0
- package/dist/storage/vector-store/backend-factory.js +33 -0
- package/dist/storage/vector-store/backend-factory.js.map +1 -0
- package/dist/storage/vector-store/json-fallback.d.ts +21 -0
- package/dist/storage/vector-store/json-fallback.d.ts.map +1 -0
- package/dist/storage/vector-store/json-fallback.js +85 -0
- package/dist/storage/vector-store/json-fallback.js.map +1 -0
- package/dist/storage/vector-store/migrator.d.ts +10 -0
- package/dist/storage/vector-store/migrator.d.ts.map +1 -0
- package/dist/storage/vector-store/migrator.js +139 -0
- package/dist/storage/vector-store/migrator.js.map +1 -0
- package/dist/storage/vector-store/sqlite-adapter.d.ts +28 -0
- package/dist/storage/vector-store/sqlite-adapter.d.ts.map +1 -0
- package/dist/storage/vector-store/sqlite-adapter.js +142 -0
- package/dist/storage/vector-store/sqlite-adapter.js.map +1 -0
- package/dist/tools/ci-planu-handler.d.ts +8 -0
- package/dist/tools/ci-planu-handler.d.ts.map +1 -0
- package/dist/tools/ci-planu-handler.js +44 -0
- package/dist/tools/ci-planu-handler.js.map +1 -0
- package/dist/tools/create-spec/constitution-validator.d.ts +4 -0
- package/dist/tools/create-spec/constitution-validator.d.ts.map +1 -0
- package/dist/tools/create-spec/constitution-validator.js +37 -0
- package/dist/tools/create-spec/constitution-validator.js.map +1 -0
- package/dist/tools/create-spec/post-creation.d.ts +11 -0
- package/dist/tools/create-spec/post-creation.d.ts.map +1 -0
- package/dist/tools/create-spec/post-creation.js +48 -0
- package/dist/tools/create-spec/post-creation.js.map +1 -0
- package/dist/tools/create-spec/spec-builder.d.ts +14 -0
- package/dist/tools/create-spec/spec-builder.d.ts.map +1 -0
- package/dist/tools/create-spec/spec-builder.js +131 -0
- package/dist/tools/create-spec/spec-builder.js.map +1 -0
- package/dist/tools/create-spec.d.ts.map +1 -1
- package/dist/tools/create-spec.js +42 -172
- package/dist/tools/create-spec.js.map +1 -1
- package/dist/tools/init-project/handler.d.ts.map +1 -1
- package/dist/tools/init-project/handler.js +24 -159
- package/dist/tools/init-project/handler.js.map +1 -1
- package/dist/tools/init-project/result-builder.d.ts +4 -0
- package/dist/tools/init-project/result-builder.d.ts.map +1 -0
- package/dist/tools/init-project/result-builder.js +150 -0
- package/dist/tools/init-project/result-builder.js.map +1 -0
- package/dist/tools/learn.d.ts.map +1 -1
- package/dist/tools/learn.js +67 -14
- package/dist/tools/learn.js.map +1 -1
- package/dist/tools/recommend-model-handler.d.ts +8 -0
- package/dist/tools/recommend-model-handler.d.ts.map +1 -0
- package/dist/tools/recommend-model-handler.js +65 -0
- package/dist/tools/recommend-model-handler.js.map +1 -0
- package/dist/tools/register-ci-tools.d.ts.map +1 -1
- package/dist/tools/register-ci-tools.js +36 -0
- package/dist/tools/register-ci-tools.js.map +1 -1
- package/dist/tools/register-model-tools.d.ts +3 -0
- package/dist/tools/register-model-tools.d.ts.map +1 -0
- package/dist/tools/register-model-tools.js +50 -0
- package/dist/tools/register-model-tools.js.map +1 -0
- package/dist/tools/register-search-tools.d.ts +7 -0
- package/dist/tools/register-search-tools.d.ts.map +1 -0
- package/dist/tools/register-search-tools.js +34 -0
- package/dist/tools/register-search-tools.js.map +1 -0
- package/dist/tools/register-template-tools.d.ts.map +1 -1
- package/dist/tools/register-template-tools.js +21 -8
- package/dist/tools/register-template-tools.js.map +1 -1
- package/dist/tools/register-transform-tools.d.ts +3 -0
- package/dist/tools/register-transform-tools.d.ts.map +1 -0
- package/dist/tools/register-transform-tools.js +29 -0
- package/dist/tools/register-transform-tools.js.map +1 -0
- package/dist/tools/semantic-search-handler.d.ts +7 -0
- package/dist/tools/semantic-search-handler.d.ts.map +1 -0
- package/dist/tools/semantic-search-handler.js +72 -0
- package/dist/tools/semantic-search-handler.js.map +1 -0
- package/dist/tools/spec-templates.d.ts +1 -1
- package/dist/tools/spec-templates.d.ts.map +1 -1
- package/dist/tools/spec-templates.js +20 -6
- package/dist/tools/spec-templates.js.map +1 -1
- package/dist/tools/transform-code-handler.d.ts +7 -0
- package/dist/tools/transform-code-handler.d.ts.map +1 -0
- package/dist/tools/transform-code-handler.js +58 -0
- package/dist/tools/transform-code-handler.js.map +1 -0
- package/dist/types/advanced-framework.d.ts +47 -0
- package/dist/types/advanced-framework.d.ts.map +1 -0
- package/dist/types/advanced-framework.js +3 -0
- package/dist/types/advanced-framework.js.map +1 -0
- package/dist/types/ci.d.ts +51 -0
- package/dist/types/ci.d.ts.map +1 -1
- package/dist/types/code-transforms.d.ts +114 -0
- package/dist/types/code-transforms.d.ts.map +1 -0
- package/dist/types/code-transforms.js +11 -0
- package/dist/types/code-transforms.js.map +1 -0
- package/dist/types/css-framework.d.ts +110 -0
- package/dist/types/css-framework.d.ts.map +1 -0
- package/dist/types/css-framework.js +3 -0
- package/dist/types/css-framework.js.map +1 -0
- package/dist/types/dashboard.d.ts +77 -0
- package/dist/types/dashboard.d.ts.map +1 -0
- package/dist/types/dashboard.js +2 -0
- package/dist/types/dashboard.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/model-routing.d.ts +127 -0
- package/dist/types/model-routing.d.ts.map +1 -0
- package/dist/types/model-routing.js +3 -0
- package/dist/types/model-routing.js.map +1 -0
- package/dist/types/project/core.d.ts +46 -5
- package/dist/types/project/core.d.ts.map +1 -1
- package/dist/types/spec/core.d.ts +28 -1
- package/dist/types/spec/core.d.ts.map +1 -1
- package/dist/types/spec/inputs.d.ts +1 -6
- package/dist/types/spec/inputs.d.ts.map +1 -1
- package/dist/types/spec-templates.d.ts +51 -1
- package/dist/types/spec-templates.d.ts.map +1 -1
- package/dist/types/ui.d.ts +3 -231
- package/dist/types/ui.d.ts.map +1 -1
- package/dist/types/ui.js +7 -1
- package/dist/types/ui.js.map +1 -1
- package/dist/types/vector-store.d.ts +144 -0
- package/dist/types/vector-store.d.ts.map +1 -0
- package/dist/types/vector-store.js +3 -0
- package/dist/types/vector-store.js.map +1 -0
- package/package.json +1 -1
- package/src/config/model-routing-rules.json +98 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"rules": [
|
|
4
|
+
{
|
|
5
|
+
"id": "haiku-simple-readonly",
|
|
6
|
+
"name": "Haiku for simple read-only tasks",
|
|
7
|
+
"conditions": [
|
|
8
|
+
{ "signal": "criteriaCount", "operator": "lte", "value": 5 },
|
|
9
|
+
{ "signal": "fileCount", "operator": "lte", "value": 3 },
|
|
10
|
+
{ "signal": "isReadOnly", "operator": "eq", "value": true }
|
|
11
|
+
],
|
|
12
|
+
"result": "haiku",
|
|
13
|
+
"weight": 1.0
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "haiku-search",
|
|
17
|
+
"name": "Haiku for search/explore tasks",
|
|
18
|
+
"conditions": [
|
|
19
|
+
{ "signal": "taskType", "operator": "eq", "value": "search" },
|
|
20
|
+
{ "signal": "criteriaCount", "operator": "lte", "value": 5 }
|
|
21
|
+
],
|
|
22
|
+
"result": "haiku",
|
|
23
|
+
"weight": 0.9
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "sonnet-medium-generation",
|
|
27
|
+
"name": "Sonnet for medium code generation",
|
|
28
|
+
"conditions": [
|
|
29
|
+
{ "signal": "criteriaCount", "operator": "between", "value": [6, 15] },
|
|
30
|
+
{ "signal": "taskType", "operator": "eq", "value": "generation" }
|
|
31
|
+
],
|
|
32
|
+
"result": "sonnet",
|
|
33
|
+
"weight": 0.85
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "sonnet-medium-files",
|
|
37
|
+
"name": "Sonnet for medium file count tasks",
|
|
38
|
+
"conditions": [{ "signal": "fileCount", "operator": "between", "value": [4, 10] }],
|
|
39
|
+
"result": "sonnet",
|
|
40
|
+
"weight": 0.75
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "sonnet-refactor",
|
|
44
|
+
"name": "Sonnet for refactoring tasks",
|
|
45
|
+
"conditions": [
|
|
46
|
+
{ "signal": "taskType", "operator": "eq", "value": "refactor" },
|
|
47
|
+
{ "signal": "crossLayerCount", "operator": "lte", "value": 2 }
|
|
48
|
+
],
|
|
49
|
+
"result": "sonnet",
|
|
50
|
+
"weight": 0.8
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "opus-high-criteria",
|
|
54
|
+
"name": "Opus for specs with many criteria",
|
|
55
|
+
"conditions": [{ "signal": "criteriaCount", "operator": "gt", "value": 15 }],
|
|
56
|
+
"result": "opus",
|
|
57
|
+
"weight": 0.9
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "opus-many-files",
|
|
61
|
+
"name": "Opus for tasks touching many files",
|
|
62
|
+
"conditions": [{ "signal": "fileCount", "operator": "gt", "value": 10 }],
|
|
63
|
+
"result": "opus",
|
|
64
|
+
"weight": 0.85
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"id": "opus-cross-layer",
|
|
68
|
+
"name": "Opus for cross-layer changes",
|
|
69
|
+
"conditions": [{ "signal": "crossLayerCount", "operator": "gt", "value": 2 }],
|
|
70
|
+
"result": "opus",
|
|
71
|
+
"weight": 0.9
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"id": "opus-architecture",
|
|
75
|
+
"name": "Opus for architecture design",
|
|
76
|
+
"conditions": [{ "signal": "taskType", "operator": "eq", "value": "architecture" }],
|
|
77
|
+
"result": "opus",
|
|
78
|
+
"weight": 0.95
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"id": "opus-security",
|
|
82
|
+
"name": "Opus for security-sensitive tasks",
|
|
83
|
+
"conditions": [
|
|
84
|
+
{ "signal": "hasSecurityImplications", "operator": "eq", "value": true },
|
|
85
|
+
{ "signal": "crossLayerCount", "operator": "gt", "value": 1 }
|
|
86
|
+
],
|
|
87
|
+
"result": "opus",
|
|
88
|
+
"weight": 0.85
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": "sonnet-default",
|
|
92
|
+
"name": "Sonnet as balanced default",
|
|
93
|
+
"conditions": [],
|
|
94
|
+
"result": "sonnet",
|
|
95
|
+
"weight": 0.5
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/engine/ai-cost-estimator/core.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/engine/ai-cost-estimator/core.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAqD9B;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAmF9F"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// engine/ai-cost-estimator/core.ts — Orchestrates AI cost estimation for specs.
|
|
2
2
|
// Coordinates token-estimator + model-pricing to produce AiCostEstimateResult.
|
|
3
|
-
import { readFile } from 'node:fs/promises';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
3
|
import { loadPricingConfig, getAllModels, calculateCost, calculateAgentTurns, isPricingStale, } from './model-pricing.js';
|
|
6
4
|
import { buildTokenEstimate } from './token-estimator.js';
|
|
5
|
+
import { loadSpecContent, countAcceptanceCriteria, readUsageAvgTokensPerCall, } from './spec-loader.js';
|
|
6
|
+
import { selectRecommendedModel, buildRecommendationReason, formatMarkdownTable, } from './recommender.js';
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
// Complexity thresholds
|
|
9
9
|
// ---------------------------------------------------------------------------
|
|
@@ -30,206 +30,6 @@ function getComplexityLevel(acCount) {
|
|
|
30
30
|
return 'high';
|
|
31
31
|
}
|
|
32
32
|
// ---------------------------------------------------------------------------
|
|
33
|
-
// Spec content loading
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
/**
|
|
36
|
-
* Reads spec content from a sdd/specs directory.
|
|
37
|
-
* Tries to find the spec directory by matching specId prefix.
|
|
38
|
-
*/
|
|
39
|
-
async function loadSpecContent(specId) {
|
|
40
|
-
// Try modern location first, fallback to legacy
|
|
41
|
-
let specsRoot = 'planu/specs';
|
|
42
|
-
try {
|
|
43
|
-
const { access: fsAccess } = await import('node:fs/promises');
|
|
44
|
-
await fsAccess(specsRoot);
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
specsRoot = 'docs/sdd/specs';
|
|
48
|
-
}
|
|
49
|
-
const { readdir } = await import('node:fs/promises');
|
|
50
|
-
let specDir = null;
|
|
51
|
-
try {
|
|
52
|
-
const topEntries = await readdir(specsRoot);
|
|
53
|
-
// Try flat layout first: planu/specs/SPEC-069-name/ or docs/sdd/specs/SPEC-069-name/
|
|
54
|
-
const flatMatch = topEntries.find((e) => e.startsWith(specId));
|
|
55
|
-
if (flatMatch) {
|
|
56
|
-
specDir = join(specsRoot, flatMatch);
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
// Try nested layout: planu/specs/{feature}/SPEC-069-name/
|
|
60
|
-
for (const group of topEntries) {
|
|
61
|
-
try {
|
|
62
|
-
const groupEntries = await readdir(join(specsRoot, group));
|
|
63
|
-
const nestedMatch = groupEntries.find((e) => e.startsWith(specId));
|
|
64
|
-
if (nestedMatch) {
|
|
65
|
-
specDir = join(specsRoot, group, nestedMatch);
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
// Not a directory — skip
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
throw new Error(`Spec directory not found at "${specsRoot}". ` +
|
|
77
|
-
'Make sure you are running from the project root.');
|
|
78
|
-
}
|
|
79
|
-
if (!specDir) {
|
|
80
|
-
throw new Error(`Spec "${specId}" not found in "${specsRoot}". ` + 'Check that the spec directory exists.');
|
|
81
|
-
}
|
|
82
|
-
const parts = [];
|
|
83
|
-
// Try modern names first, fallback to legacy — only read one of each pair
|
|
84
|
-
for (const [modern, legacy] of [
|
|
85
|
-
['spec.md', 'HU.md'],
|
|
86
|
-
['technical.md', 'FICHA-TECNICA.md'],
|
|
87
|
-
]) {
|
|
88
|
-
let found = false;
|
|
89
|
-
for (const filename of [modern, legacy]) {
|
|
90
|
-
if (found) {
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
try {
|
|
94
|
-
const content = await readFile(join(specDir, filename), 'utf-8');
|
|
95
|
-
parts.push(content);
|
|
96
|
-
found = true;
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
// File not present — try next
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (parts.length === 0) {
|
|
104
|
-
throw new Error(`Spec "${specId}" has no spec files in "${specDir}". ` +
|
|
105
|
-
'Cannot estimate without spec content.');
|
|
106
|
-
}
|
|
107
|
-
return { content: parts.join('\n\n'), specDir };
|
|
108
|
-
}
|
|
109
|
-
/** Counts acceptance criteria (lines starting with "- [ ]" or "- [x]") in spec content. */
|
|
110
|
-
function countAcceptanceCriteria(specContent) {
|
|
111
|
-
const matches = specContent.match(/^- \[[ xX]\]/gm);
|
|
112
|
-
return matches?.length ?? 0;
|
|
113
|
-
}
|
|
114
|
-
// ---------------------------------------------------------------------------
|
|
115
|
-
// Usage calibration
|
|
116
|
-
// ---------------------------------------------------------------------------
|
|
117
|
-
/** Reads average tokens per call from usage.json if available. */
|
|
118
|
-
async function readUsageAvgTokensPerCall() {
|
|
119
|
-
try {
|
|
120
|
-
const { readFile: rf } = await import('node:fs/promises');
|
|
121
|
-
const raw = await rf('data/global/usage.json', 'utf-8');
|
|
122
|
-
/* v8 ignore start */
|
|
123
|
-
const log = JSON.parse(raw);
|
|
124
|
-
if (log.events.length === 0) {
|
|
125
|
-
return undefined;
|
|
126
|
-
}
|
|
127
|
-
// Usage events don't track token counts — return undefined to use defaults
|
|
128
|
-
return undefined;
|
|
129
|
-
/* v8 ignore stop */
|
|
130
|
-
}
|
|
131
|
-
catch {
|
|
132
|
-
return undefined;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
|
-
// Recommendation logic
|
|
137
|
-
// ---------------------------------------------------------------------------
|
|
138
|
-
/** Selects the recommended model based on spec complexity. */
|
|
139
|
-
function selectRecommendedModel(models, complexity) {
|
|
140
|
-
const preferencesByComplexity = {
|
|
141
|
-
low: [
|
|
142
|
-
'claude-haiku-3-5',
|
|
143
|
-
'gemini-2-5-pro',
|
|
144
|
-
'gpt-4-1',
|
|
145
|
-
'gpt-4o',
|
|
146
|
-
'claude-sonnet-4',
|
|
147
|
-
'claude-opus-4',
|
|
148
|
-
],
|
|
149
|
-
medium: [
|
|
150
|
-
'claude-sonnet-4',
|
|
151
|
-
'gpt-4o',
|
|
152
|
-
'gpt-4-1',
|
|
153
|
-
'gemini-2-5-pro',
|
|
154
|
-
'claude-haiku-3-5',
|
|
155
|
-
'claude-opus-4',
|
|
156
|
-
],
|
|
157
|
-
high: [
|
|
158
|
-
'claude-opus-4',
|
|
159
|
-
'claude-sonnet-4',
|
|
160
|
-
'gpt-4o',
|
|
161
|
-
'gpt-4-1',
|
|
162
|
-
'gemini-2-5-pro',
|
|
163
|
-
'claude-haiku-3-5',
|
|
164
|
-
],
|
|
165
|
-
};
|
|
166
|
-
const preferences = preferencesByComplexity[complexity] ?? preferencesByComplexity.medium ?? [];
|
|
167
|
-
for (const modelId of preferences) {
|
|
168
|
-
const model = models.find((m) => m.id === modelId);
|
|
169
|
-
if (model) {
|
|
170
|
-
return model;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
// Fallback: cheapest model
|
|
174
|
-
/* v8 ignore start */
|
|
175
|
-
const sorted = [...models].sort((a, b) => a.inputPricePerMillion - b.inputPricePerMillion);
|
|
176
|
-
const first = sorted[0];
|
|
177
|
-
if (!first) {
|
|
178
|
-
throw new Error('No models available in pricing config');
|
|
179
|
-
}
|
|
180
|
-
return first;
|
|
181
|
-
/* v8 ignore stop */
|
|
182
|
-
}
|
|
183
|
-
/** Builds a human-readable recommendation reason. */
|
|
184
|
-
function buildRecommendationReason(model, complexity, savingsVsMostExpensive) {
|
|
185
|
-
const complexityLabel = { low: 'baja', medium: 'media', high: 'alta' }[complexity];
|
|
186
|
-
const baseReason = `Para complejidad ${complexityLabel}, **${model.displayName}** ofrece `;
|
|
187
|
-
if (complexity === 'low') {
|
|
188
|
-
return (baseReason +
|
|
189
|
-
`el mejor precio sin sacrificar calidad. ` +
|
|
190
|
-
`Ahorro estimado vs modelo más caro: $${savingsVsMostExpensive.toFixed(4)} USD.`);
|
|
191
|
-
}
|
|
192
|
-
if (complexity === 'medium') {
|
|
193
|
-
return (baseReason +
|
|
194
|
-
`el mejor balance calidad/precio. ` +
|
|
195
|
-
`Ahorro estimado vs modelo más caro: $${savingsVsMostExpensive.toFixed(4)} USD.`);
|
|
196
|
-
}
|
|
197
|
-
return (baseReason +
|
|
198
|
-
`máxima calidad para specs complejas. ` +
|
|
199
|
-
`El costo adicional se justifica por la reducción de iteraciones.`);
|
|
200
|
-
}
|
|
201
|
-
// ---------------------------------------------------------------------------
|
|
202
|
-
// Markdown formatting
|
|
203
|
-
// ---------------------------------------------------------------------------
|
|
204
|
-
/** Formats the cost estimates as a markdown table. */
|
|
205
|
-
function formatMarkdownTable(estimates, recommendedModelId, recommendationReason, staleWarning) {
|
|
206
|
-
const header = '| Modelo | Tokens Input | Tokens Output | Costo Estimado | Rango (±) | Agent Turns |\n' +
|
|
207
|
-
'|--------|-------------|---------------|----------------|-----------|-------------|';
|
|
208
|
-
const rows = estimates.map((est) => {
|
|
209
|
-
const marker = est.modelId === recommendedModelId ? ' ⭐' : '';
|
|
210
|
-
const cost = `$${est.estimatedCostUsd.toFixed(4)}`;
|
|
211
|
-
const range = `±${est.confidenceRangePct}%`;
|
|
212
|
-
return (`| ${est.displayName}${marker} | ${est.inputTokens.toLocaleString()} | ` +
|
|
213
|
-
`${est.outputTokens.toLocaleString()} | ${cost} | ${range} | ${est.agentTurns} |`);
|
|
214
|
-
});
|
|
215
|
-
const recommended = estimates.find((e) => e.modelId === recommendedModelId);
|
|
216
|
-
const recommendedName = recommended?.displayName ?? recommendedModelId;
|
|
217
|
-
const lines = [
|
|
218
|
-
'## Estimación de Costo por Modelo IA',
|
|
219
|
-
'',
|
|
220
|
-
header,
|
|
221
|
-
...rows,
|
|
222
|
-
'',
|
|
223
|
-
`## Recomendación: ${recommendedName}`,
|
|
224
|
-
'',
|
|
225
|
-
recommendationReason,
|
|
226
|
-
];
|
|
227
|
-
if (staleWarning) {
|
|
228
|
-
lines.push('', `> **Aviso**: ${staleWarning}`);
|
|
229
|
-
}
|
|
230
|
-
return lines.join('\n');
|
|
231
|
-
}
|
|
232
|
-
// ---------------------------------------------------------------------------
|
|
233
33
|
// Main orchestrator
|
|
234
34
|
// ---------------------------------------------------------------------------
|
|
235
35
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/engine/ai-cost-estimator/core.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,+EAA+E;
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/engine/ai-cost-estimator/core.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,+EAA+E;AAO/E,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAE1B,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAChC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAEpC,sFAAsF;AACtF,SAAS,qBAAqB,CAAC,OAAe;IAC5C,IAAI,OAAO,IAAI,qBAAqB,EAAE,CAAC;QACrC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,OAAO,IAAI,wBAAwB,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,+DAA+D;AAC/D,SAAS,kBAAkB,CAAC,OAAe;IACzC,IAAI,OAAO,IAAI,qBAAqB,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,IAAI,wBAAwB,EAAE,CAAC;QACxC,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAA0B;IAC7D,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;IAEtC,uBAAuB;IACvB,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;IAErD,yBAAyB;IACzB,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;IAEpC,0BAA0B;IAC1B,MAAM,QAAQ,GAAG,MAAM,yBAAyB,EAAE,CAAC;IACnD,MAAM,aAAa,GAAG,MAAM,kBAAkB,CAC5C,WAAW,EACX,CAAC,EAAE,uDAAuD;IAC1D,OAAO,EACP,WAAW,EACX,MAAM,EACN,QAAQ,CACT,CAAC;IAEF,uCAAuC;IACvC,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,kBAAkB,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAE1D,mCAAmC;IACnC,MAAM,SAAS,GAAqB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACvD,MAAM,gBAAgB,GAAG,aAAa,CACpC,KAAK,EACL,aAAa,CAAC,WAAW,EACzB,aAAa,CAAC,YAAY,CAC3B,CAAC;QACF,MAAM,UAAU,GAAG,mBAAmB,CAAC,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;QAE3E,OAAO;YACL,OAAO,EAAE,KAAK,CAAC,EAAE;YACjB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,WAAW,EAAE,aAAa,CAAC,WAAW;YACtC,YAAY,EAAE,aAAa,CAAC,YAAY;YACxC,gBAAgB;YAChB,kBAAkB;YAClB,UAAU;SACX,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,8BAA8B;IAC9B,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAEpE,4CAA4C;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACtE,MAAM,mBAAmB,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,gBAAgB,CAAC,EAAE,CAAC,CAAC;IACrF,MAAM,eAAe,GAAG,mBAAmB,EAAE,gBAAgB,IAAI,CAAC,CAAC;IACnE,MAAM,uBAAuB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC,CAAC;IAEvE,MAAM,oBAAoB,GAAG,yBAAyB,CACpD,gBAAgB,EAChB,UAAU,EACV,uBAAuB,CACxB,CAAC;IAEF,+BAA+B;IAC/B,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,WAAW,CAAC;QACrD,CAAC,CAAC,8EAA8E,MAAM,CAAC,WAAW,KAAK;YACrG,sEAAsE;QACxE,CAAC,CAAC,EAAE,CAAC;IAEP,2BAA2B;IAC3B,MAAM,aAAa,GAAG,mBAAmB,CACvC,SAAS,EACT,gBAAgB,CAAC,EAAE,EACnB,oBAAoB,EACpB,YAAY,CACb,CAAC;IAEF,OAAO;QACL,MAAM;QACN,SAAS;QACT,kBAAkB,EAAE,gBAAgB,CAAC,EAAE;QACvC,oBAAoB;QACpB,uBAAuB;QACvB,aAAa;KACd,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AiCostEstimate, AiModelConfig } from '../../types/index.js';
|
|
2
|
+
/** Selects the recommended model based on spec complexity. */
|
|
3
|
+
export declare function selectRecommendedModel(models: readonly AiModelConfig[], complexity: 'low' | 'medium' | 'high'): AiModelConfig;
|
|
4
|
+
/** Builds a human-readable recommendation reason. */
|
|
5
|
+
export declare function buildRecommendationReason(model: AiModelConfig, complexity: 'low' | 'medium' | 'high', savingsVsMostExpensive: number): string;
|
|
6
|
+
/** Formats the cost estimates as a markdown table. */
|
|
7
|
+
export declare function formatMarkdownTable(estimates: readonly AiCostEstimate[], recommendedModelId: string, recommendationReason: string, staleWarning: string): string;
|
|
8
|
+
//# sourceMappingURL=recommender.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommender.d.ts","sourceRoot":"","sources":["../../../src/engine/ai-cost-estimator/recommender.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1E,8DAA8D;AAC9D,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GACpC,aAAa,CA8Cf;AAED,qDAAqD;AACrD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,EACrC,sBAAsB,EAAE,MAAM,GAC7B,MAAM,CA0BR;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,cAAc,EAAE,EACpC,kBAAkB,EAAE,MAAM,EAC1B,oBAAoB,EAAE,MAAM,EAC5B,YAAY,EAAE,MAAM,GACnB,MAAM,CAkCR"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// engine/ai-cost-estimator/recommender.ts — Model recommendation and markdown formatting.
|
|
2
|
+
// Extracted from core.ts to keep file sizes within limits.
|
|
3
|
+
/** Selects the recommended model based on spec complexity. */
|
|
4
|
+
export function selectRecommendedModel(models, complexity) {
|
|
5
|
+
const preferencesByComplexity = {
|
|
6
|
+
low: [
|
|
7
|
+
'claude-haiku-3-5',
|
|
8
|
+
'gemini-2-5-pro',
|
|
9
|
+
'gpt-4-1',
|
|
10
|
+
'gpt-4o',
|
|
11
|
+
'claude-sonnet-4',
|
|
12
|
+
'claude-opus-4',
|
|
13
|
+
],
|
|
14
|
+
medium: [
|
|
15
|
+
'claude-sonnet-4',
|
|
16
|
+
'gpt-4o',
|
|
17
|
+
'gpt-4-1',
|
|
18
|
+
'gemini-2-5-pro',
|
|
19
|
+
'claude-haiku-3-5',
|
|
20
|
+
'claude-opus-4',
|
|
21
|
+
],
|
|
22
|
+
high: [
|
|
23
|
+
'claude-opus-4',
|
|
24
|
+
'claude-sonnet-4',
|
|
25
|
+
'gpt-4o',
|
|
26
|
+
'gpt-4-1',
|
|
27
|
+
'gemini-2-5-pro',
|
|
28
|
+
'claude-haiku-3-5',
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
const preferences = preferencesByComplexity[complexity] ?? preferencesByComplexity.medium ?? [];
|
|
32
|
+
for (const modelId of preferences) {
|
|
33
|
+
const model = models.find((m) => m.id === modelId);
|
|
34
|
+
if (model) {
|
|
35
|
+
return model;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Fallback: cheapest model
|
|
39
|
+
/* v8 ignore start */
|
|
40
|
+
const sorted = [...models].sort((a, b) => a.inputPricePerMillion - b.inputPricePerMillion);
|
|
41
|
+
const first = sorted[0];
|
|
42
|
+
if (!first) {
|
|
43
|
+
throw new Error('No models available in pricing config');
|
|
44
|
+
}
|
|
45
|
+
return first;
|
|
46
|
+
/* v8 ignore stop */
|
|
47
|
+
}
|
|
48
|
+
/** Builds a human-readable recommendation reason. */
|
|
49
|
+
export function buildRecommendationReason(model, complexity, savingsVsMostExpensive) {
|
|
50
|
+
const complexityLabel = { low: 'baja', medium: 'media', high: 'alta' }[complexity];
|
|
51
|
+
const baseReason = `Para complejidad ${complexityLabel}, **${model.displayName}** ofrece `;
|
|
52
|
+
if (complexity === 'low') {
|
|
53
|
+
return (baseReason +
|
|
54
|
+
`el mejor precio sin sacrificar calidad. ` +
|
|
55
|
+
`Ahorro estimado vs modelo más caro: $${savingsVsMostExpensive.toFixed(4)} USD.`);
|
|
56
|
+
}
|
|
57
|
+
if (complexity === 'medium') {
|
|
58
|
+
return (baseReason +
|
|
59
|
+
`el mejor balance calidad/precio. ` +
|
|
60
|
+
`Ahorro estimado vs modelo más caro: $${savingsVsMostExpensive.toFixed(4)} USD.`);
|
|
61
|
+
}
|
|
62
|
+
return (baseReason +
|
|
63
|
+
`máxima calidad para specs complejas. ` +
|
|
64
|
+
`El costo adicional se justifica por la reducción de iteraciones.`);
|
|
65
|
+
}
|
|
66
|
+
/** Formats the cost estimates as a markdown table. */
|
|
67
|
+
export function formatMarkdownTable(estimates, recommendedModelId, recommendationReason, staleWarning) {
|
|
68
|
+
const header = '| Modelo | Tokens Input | Tokens Output | Costo Estimado | Rango (±) | Agent Turns |\n' +
|
|
69
|
+
'|--------|-------------|---------------|----------------|-----------|-------------|';
|
|
70
|
+
const rows = estimates.map((est) => {
|
|
71
|
+
const marker = est.modelId === recommendedModelId ? ' ⭐' : '';
|
|
72
|
+
const cost = `$${est.estimatedCostUsd.toFixed(4)}`;
|
|
73
|
+
const range = `±${est.confidenceRangePct}%`;
|
|
74
|
+
return (`| ${est.displayName}${marker} | ${est.inputTokens.toLocaleString()} | ` +
|
|
75
|
+
`${est.outputTokens.toLocaleString()} | ${cost} | ${range} | ${est.agentTurns} |`);
|
|
76
|
+
});
|
|
77
|
+
const recommended = estimates.find((e) => e.modelId === recommendedModelId);
|
|
78
|
+
const recommendedName = recommended?.displayName ?? recommendedModelId;
|
|
79
|
+
const lines = [
|
|
80
|
+
'## Estimación de Costo por Modelo IA',
|
|
81
|
+
'',
|
|
82
|
+
header,
|
|
83
|
+
...rows,
|
|
84
|
+
'',
|
|
85
|
+
`## Recomendación: ${recommendedName}`,
|
|
86
|
+
'',
|
|
87
|
+
recommendationReason,
|
|
88
|
+
];
|
|
89
|
+
if (staleWarning) {
|
|
90
|
+
lines.push('', `> **Aviso**: ${staleWarning}`);
|
|
91
|
+
}
|
|
92
|
+
return lines.join('\n');
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=recommender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommender.js","sourceRoot":"","sources":["../../../src/engine/ai-cost-estimator/recommender.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads spec content from a sdd/specs directory.
|
|
3
|
+
* Tries to find the spec directory by matching specId prefix.
|
|
4
|
+
*/
|
|
5
|
+
export declare function loadSpecContent(specId: string): Promise<{
|
|
6
|
+
content: string;
|
|
7
|
+
specDir: string;
|
|
8
|
+
}>;
|
|
9
|
+
/** Counts acceptance criteria (lines starting with "- [ ]" or "- [x]") in spec content. */
|
|
10
|
+
export declare function countAcceptanceCriteria(specContent: string): number;
|
|
11
|
+
/** Reads average tokens per call from usage.json if available. */
|
|
12
|
+
export declare function readUsageAvgTokensPerCall(): Promise<number | undefined>;
|
|
13
|
+
//# sourceMappingURL=spec-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-loader.d.ts","sourceRoot":"","sources":["../../../src/engine/ai-cost-estimator/spec-loader.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA6E/C;AAED,2FAA2F;AAC3F,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED,kEAAkE;AAClE,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAe7E"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// engine/ai-cost-estimator/spec-loader.ts — Loads spec content and counts acceptance criteria.
|
|
2
|
+
// Extracted from core.ts to keep file sizes within limits.
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
/**
|
|
6
|
+
* Reads spec content from a sdd/specs directory.
|
|
7
|
+
* Tries to find the spec directory by matching specId prefix.
|
|
8
|
+
*/
|
|
9
|
+
export async function loadSpecContent(specId) {
|
|
10
|
+
// Try modern location first, fallback to legacy
|
|
11
|
+
let specsRoot = 'planu/specs';
|
|
12
|
+
try {
|
|
13
|
+
const { access: fsAccess } = await import('node:fs/promises');
|
|
14
|
+
await fsAccess(specsRoot);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
specsRoot = 'docs/sdd/specs';
|
|
18
|
+
}
|
|
19
|
+
const { readdir } = await import('node:fs/promises');
|
|
20
|
+
let specDir = null;
|
|
21
|
+
try {
|
|
22
|
+
const topEntries = await readdir(specsRoot);
|
|
23
|
+
// Try flat layout first: planu/specs/SPEC-069-name/ or docs/sdd/specs/SPEC-069-name/
|
|
24
|
+
const flatMatch = topEntries.find((e) => e.startsWith(specId));
|
|
25
|
+
if (flatMatch) {
|
|
26
|
+
specDir = join(specsRoot, flatMatch);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// Try nested layout: planu/specs/{feature}/SPEC-069-name/
|
|
30
|
+
for (const group of topEntries) {
|
|
31
|
+
try {
|
|
32
|
+
const groupEntries = await readdir(join(specsRoot, group));
|
|
33
|
+
const nestedMatch = groupEntries.find((e) => e.startsWith(specId));
|
|
34
|
+
if (nestedMatch) {
|
|
35
|
+
specDir = join(specsRoot, group, nestedMatch);
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Not a directory — skip
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
throw new Error(`Spec directory not found at "${specsRoot}". ` +
|
|
47
|
+
'Make sure you are running from the project root.');
|
|
48
|
+
}
|
|
49
|
+
if (!specDir) {
|
|
50
|
+
throw new Error(`Spec "${specId}" not found in "${specsRoot}". ` + 'Check that the spec directory exists.');
|
|
51
|
+
}
|
|
52
|
+
const parts = [];
|
|
53
|
+
// Try modern names first, fallback to legacy — only read one of each pair
|
|
54
|
+
for (const [modern, legacy] of [
|
|
55
|
+
['spec.md', 'HU.md'],
|
|
56
|
+
['technical.md', 'FICHA-TECNICA.md'],
|
|
57
|
+
]) {
|
|
58
|
+
let found = false;
|
|
59
|
+
for (const filename of [modern, legacy]) {
|
|
60
|
+
if (found) {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const content = await readFile(join(specDir, filename), 'utf-8');
|
|
65
|
+
parts.push(content);
|
|
66
|
+
found = true;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// File not present — try next
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (parts.length === 0) {
|
|
74
|
+
throw new Error(`Spec "${specId}" has no spec files in "${specDir}". ` +
|
|
75
|
+
'Cannot estimate without spec content.');
|
|
76
|
+
}
|
|
77
|
+
return { content: parts.join('\n\n'), specDir };
|
|
78
|
+
}
|
|
79
|
+
/** Counts acceptance criteria (lines starting with "- [ ]" or "- [x]") in spec content. */
|
|
80
|
+
export function countAcceptanceCriteria(specContent) {
|
|
81
|
+
const matches = specContent.match(/^- \[[ xX]\]/gm);
|
|
82
|
+
return matches?.length ?? 0;
|
|
83
|
+
}
|
|
84
|
+
/** Reads average tokens per call from usage.json if available. */
|
|
85
|
+
export async function readUsageAvgTokensPerCall() {
|
|
86
|
+
try {
|
|
87
|
+
const { readFile: rf } = await import('node:fs/promises');
|
|
88
|
+
const raw = await rf('data/global/usage.json', 'utf-8');
|
|
89
|
+
/* v8 ignore start */
|
|
90
|
+
const log = JSON.parse(raw);
|
|
91
|
+
if (log.events.length === 0) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
// Usage events don't track token counts — return undefined to use defaults
|
|
95
|
+
return undefined;
|
|
96
|
+
/* v8 ignore stop */
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=spec-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-loader.js","sourceRoot":"","sources":["../../../src/engine/ai-cost-estimator/spec-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PlanuConfigOptions } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generate the YAML content for a .planu.yml configuration file.
|
|
4
|
+
* This file configures the Planu CI check workflow behavior.
|
|
5
|
+
*/
|
|
6
|
+
export declare function generatePlanuConfigYaml(options: PlanuConfigOptions): string;
|
|
7
|
+
//# sourceMappingURL=planu-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planu-config.d.ts","sourceRoot":"","sources":["../../../src/engine/ci-generator/planu-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAkD3E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// ci-generator/planu-config.ts — Generate .planu.yml config file (SPEC-066 AC-05)
|
|
2
|
+
/**
|
|
3
|
+
* Generate the YAML content for a .planu.yml configuration file.
|
|
4
|
+
* This file configures the Planu CI check workflow behavior.
|
|
5
|
+
*/
|
|
6
|
+
export function generatePlanuConfigYaml(options) {
|
|
7
|
+
const { specsDir, failOnDrift, severityThreshold, postComment, badge, include, exclude, licenseKeyRef, } = options;
|
|
8
|
+
const lines = ['# .planu.yml — Planu CI configuration', ''];
|
|
9
|
+
// Specs section
|
|
10
|
+
lines.push('specs:');
|
|
11
|
+
lines.push(` directory: ${specsDir}`);
|
|
12
|
+
if (include && include.length > 0) {
|
|
13
|
+
lines.push(' include:');
|
|
14
|
+
for (const spec of include) {
|
|
15
|
+
lines.push(` - ${spec}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (exclude && exclude.length > 0) {
|
|
19
|
+
lines.push(' exclude:');
|
|
20
|
+
for (const spec of exclude) {
|
|
21
|
+
lines.push(` - ${spec}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
lines.push('');
|
|
25
|
+
// CI section
|
|
26
|
+
lines.push('ci:');
|
|
27
|
+
lines.push(` fail-on-drift: ${String(failOnDrift)}`);
|
|
28
|
+
lines.push(` severity-threshold: ${severityThreshold}`);
|
|
29
|
+
lines.push(` post-comment: ${String(postComment)}`);
|
|
30
|
+
lines.push(` badge: ${String(badge)}`);
|
|
31
|
+
// License section
|
|
32
|
+
if (licenseKeyRef) {
|
|
33
|
+
lines.push('');
|
|
34
|
+
lines.push('license:');
|
|
35
|
+
lines.push(` key: \${${licenseKeyRef}}`);
|
|
36
|
+
}
|
|
37
|
+
lines.push('');
|
|
38
|
+
return lines.join('\n');
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=planu-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planu-config.js","sourceRoot":"","sources":["../../../src/engine/ci-generator/planu-config.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAIlF;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAA2B;IACjE,MAAM,EACJ,QAAQ,EACR,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,KAAK,EACL,OAAO,EACP,OAAO,EACP,aAAa,GACd,GAAG,OAAO,CAAC;IAEZ,MAAM,KAAK,GAAa,CAAC,uCAAuC,EAAE,EAAE,CAAC,CAAC;IAEtE,gBAAgB;IAChB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,KAAK,CAAC,IAAI,CAAC,gBAAgB,QAAQ,EAAE,CAAC,CAAC;IAEvC,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,aAAa;IACb,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACtD,KAAK,CAAC,IAAI,CAAC,yBAAyB,iBAAiB,EAAE,CAAC,CAAC;IACzD,KAAK,CAAC,IAAI,CAAC,mBAAmB,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACrD,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAExC,kBAAkB;IAClB,IAAI,aAAa,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,aAAa,aAAa,GAAG,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|